//
//  KJRequest.swift
//  LaidaShowB
//
//  Created by Met on 2020/11/25.
//  Copyright © 2020 shenyi. All rights reserved.
//

import Foundation

class KJUserModel: NSObject{
    var token: String? = ""
}

public let Req = KJRequest.shared
public let ServerUrl = "LSServerUrl"

open class KJRequest: NSObject {
    static let shared: KJRequest = {
        return KJRequest()
    }()
    
    private var um: KJUserModel?
    var userModel: KJUserModel? {
        get{
            if um != nil  {
                return um
            }
            else{
                let data = UserDefaults.standard.object(forKey: "KJUserModelCacheKey")
                if let d = data {
                    do{
                        let m = try NSKeyedUnarchiver.unarchivedObject(ofClasses: [KJUserModel.self], from: d as! Data)
                        if m is KJUserModel {
                            self.um = m as? KJUserModel
                        }
                    }
                    catch{
                        print("解析用户缓存数据失败")
                    }
                }
            }
            
            return self.um
        }
    }
    
    func updateUserModel(um: KJUserModel?) {
        guard um != nil else {
            return
        }
        
        do {
            let data = try NSKeyedArchiver.archivedData(withRootObject: um!, requiringSecureCoding: true)
            
            UserDefaults.standard.set(data, forKey: "KJUserModelCacheKey")
                
            self.um = um
        }
        catch {
            print("缓存用户数据失败")
        }
    }
    
    func removeUserModel() {
        UserDefaults.standard.removeObject(forKey: "KJUserModelCacheKey")
        self.um = nil
    }
    
    //MARK:- 网络请求
    func baseRequest(urlName: String, parameters: [String:String]?, isJsonType:Bool, caller: Any, method: BLHttpRequest.Method, needAnalysisData: Bool,complete:@escaping (Any?, NSError?) -> Void) {
        
    }
    
    func baseRequest0(urlName: String, parameters: [String:String]?, isJsonType:Bool, caller: Any, method: BLHttpRequest.Method, needAnalysisData: Bool,complete:@escaping (Any?, NSError?) -> Void) {
        
        
        func generateCacheKey() -> String{
            var key = urlName
            if let para = parameters {
                let arr = para.values.sorted { s1, s2 in
                    return s1 > s2
                }
                var vstr: String?
                for v in arr {
                    if vstr == nil {
                        vstr = v
                    }else{
                        vstr = "\(vstr!)\(v)"
                    }
                }
                if vstr != nil {
                    key = urlName + vstr!
                }
            }
            return key.md5+"KKK"
        }
        
        ///若缓存中存在数据，则从缓存中读取
        let cacheKey = generateCacheKey()
//        if let d = UserDefaults.standard.value(forKey: cacheKey) {
//            print("\n\n------------- 从缓存读取 ------------\n\n")
//            var err: NSError?
//            var data: Any? = d
//            if needAnalysisData {
//                if err == nil {
//                   (data, err) = self.analysisData(data: data)
//                }
//            }
//            if data != nil {
//                complete(data,err);
//                return
//            }
//        }
        
                
        var url = ServerUrl+urlName
        
        //若urlname以http开头，则直接使用urlName
        if urlName.count > 4 {
            let httpstr = urlName.subTo(4)
            if httpstr.contains("http") {
                url = urlName
            }
        }
        
        DispatchQueue.global().async {
        
            BLHttpRequest.sharedInstance.request(url: url, parameters: parameters, caller: caller, isJsonType:isJsonType, method: method, requestModifier: { ( req :inout URLRequest) in
                
                if self.userModel?.token != nil {
//                    req.setValue( "bearer "+self.userModel!.token!, forHTTPHeaderField: "Authorization")
//                    req.setValue("3", forHTTPHeaderField: "deviceType")
                    
                    let tk = self.userModel?.token
                    req.setValue(tk, forHTTPHeaderField: "TRSDH-Access-Token")
                
                }
                
                if isJsonType {
                    req.setValue("application/json", forHTTPHeaderField: "Content-Type")
                }
                
                let isThirdLogin = urlName.contains("auth/loginBySocial")
                
                //登录需要设置固定的token
                if urlName.contains("auth/oauth/token") || urlName.contains("auth/loginByMobile") || isThirdLogin {
                    req.setValue("Basic YXBwOmFwcC1zZWNyZXQ=", forHTTPHeaderField: "Authorization")
                    
//                    if isThirdLogin {
//                        req.setValue("multipart/form-data", forHTTPHeaderField:"Content-Type")
//                    }
                }
                
            }) { (data, err) in
                var data: Any? = data
                
                
                if let d = data as? Data {
                    //缓存网络数据
                    UserDefaults.standard.setValue(d, forKey: cacheKey)
                }
                
                
                var err: NSError? = err
                if needAnalysisData {
                    if err == nil {
                       (data, err) = self.analysisData(data: data)
                    }
                }
                
                DispatchQueue.main.async {
                    complete(data,err)
                }
            }
        }
    }
    
    func get(urlName: String, parameters: [String:String]?, isJsonType:Bool = false, caller: Any, complete:@escaping (Any?, NSError?) -> Void) {
        self.baseRequest(urlName: urlName, parameters: parameters,isJsonType:isJsonType, caller: caller, method: BLHttpRequest.Method.GET, needAnalysisData: true, complete: complete)
    }
    
    func post(urlName: String, parameters: [String:String]?, isJsonType:Bool = false, caller: Any, complete:@escaping (Any?, NSError?) -> Void) {
        self.baseRequest(urlName: urlName, parameters: parameters,isJsonType:isJsonType, caller: caller, method: BLHttpRequest.Method.POST, needAnalysisData: true, complete: complete)
    }
    
    func cancleAllRequest() {
        BLHttpRequest.sharedInstance.cancleAllRequest()
    }
    
    // MARK: - 上传文件
    ///filePaths: Any可为路径，或UIImage对象
    func uploadImgs(urlName: String, filePaths:[Any], para:[String:String]?, complete:@escaping (Any?, NSError?) -> Void) {
        
        let url = ServerUrl+urlName
        
        DispatchQueue.global().async {
        
            BLHttpRequest.sharedInstance.uploadImgs(url: url, filePaths: filePaths, para: para, requestModifier: { ( req :inout URLRequest) in
                if self.userModel?.token != nil {
                    req.setValue( "bearer "+self.userModel!.token!, forHTTPHeaderField: "Authorization")
                }
            }) { (data,err1) in
                
//                if err1?.code == 15 {
//                    print("请求被取消")
//                    return;
//                }
                
                var data: Any? = data
                var err: NSError? = err1

                if err == nil {
                   (data, err) = self.analysisData(data: data)
                }
                DispatchQueue.main.async {
                 
                    complete(data,err)
                }
            }
        }
    }
    
    /// 上传视频
    /// - Parameters:
    ///   - urlName: 路径
    ///   - videoPath: 视频路径
    ///   - videoCoverPath: 封面路径
    ///   - para: 参数
    ///   - complete: 回调
    func uploadVideo(urlName: String, videoPath: String?, videoCoverPath: String?, para:[String:String]?, complete:@escaping (Any?, NSError?) -> Void) {
        let url = ServerUrl+urlName
        
        DispatchQueue.global().async {
        
            BLHttpRequest.sharedInstance.uploadVideo(url: url, videoPath: videoPath, videoCoverPath: videoCoverPath, para: para, requestModifier: { ( req :inout URLRequest) in
                if self.userModel?.token != nil {
                    req.setValue( "bearer "+self.userModel!.token!, forHTTPHeaderField: "Authorization")
                }
            }) { (data,err) in
                var data: Any? = data
                var err: NSError? = err
                if err == nil {
                   (data, err) = self.analysisData(data: data)
                }
                DispatchQueue.main.async {
                    complete(data,err)
                }
            }
        }
    }
    
    /// 上传音频
    /// - Parameters:
    ///   - urlName: 接口路径
    ///   - audioPath: 音频路径
    ///   - videoCoverPath: 封面路径
    ///   - para: 参数
    ///   - complete: 回调
    func uploadAudio(urlName: String, audioPath: String?, para:[String:String]?, complete:@escaping (Any?, NSError?) -> Void) {
        let url = ServerUrl+urlName
        
        DispatchQueue.global().async {
        
            let str = (audioPath as NSString?)?.lastPathComponent
            let n = (str as NSString?)?.deletingPathExtension
            
            BLHttpRequest.sharedInstance.uploadAudio(url: url, audioPath: audioPath, audioName: n, para: para, requestModifier: { ( req :inout URLRequest) in
                if self.userModel?.token != nil {
                    req.setValue( "bearer "+self.userModel!.token!, forHTTPHeaderField: "Authorization")
                }
            }) { (data,err) in
                var data: Any? = data
                var err: NSError? = err
                if err == nil {
                   (data, err) = self.analysisData(data: data)
                }
                DispatchQueue.main.async {
                    complete(data,err)
                }
            }
        }
    }
    
    // MARK: - 下载文件
    func download(url: String, toDir:String, complete:@escaping (Data?, NSError?) -> Void) {
        BLHttpRequest.sharedInstance.download(url: url, toDir: toDir, requestModifier: { (req) in
            if self.userModel?.token != nil {
                req.setValue( "bearer "+self.userModel!.token!, forHTTPHeaderField: "Authorization")
            }
        }) { (data, err) in
            DispatchQueue.main.async {
                complete(data,err)
            }
        }
    }
    
    //MARK:- 数据解析
    func analysisData(data: Any?) -> (Any?, NSError?){
        var err : NSError?
        let data = data as? Data
        if let d = data {
            do{
                let dic = try JSONSerialization.jsonObject(with: d, options: JSONSerialization.ReadingOptions.mutableContainers)
                if dic is Dictionary<String, Any> {
                    let tdic = dic as! Dictionary<String, Any>
                    if tdic.isEmpty==false {
                        let code = tdic["code"]
                        
                        if let code = code {
                            
                            if let c = code as? Int {
                                if c == 200 {
                                    return (tdic["data"], nil)
                                }else{
                                    var mg = "操作失败"
                                    if let msg = tdic["msg"] as? String {
                                        mg = msg
                                    }
                                    err = BLError.error(msg: mg)
                                    return (nil, err)
                                }
                            }
                            
                            if code is String {
                                
                                //返回码和错误消息都为空，则也认为是成功
                                var isCodeNilAndErrNil = false
                                if code as! String == "" {
                                    let errMsg = tdic["msg"]
                                    if let msg = errMsg {
                                        if msg is String {
                                            if msg as! String == "" {
                                                isCodeNilAndErrNil = true
                                            }
                                        }
                                    }
                                }
                                
                                if code as! String == "success" {
                                    return (tdic["data"], err)
                                }else if isCodeNilAndErrNil {
                                    
                                    var d = tdic["data"]
                                    if let d1 = d as? String {
                                        if d1 == "" {
                                            d = tdic["rtnResult"]
                                        }
                                    }
                                    return (d, err)
//                                    return (tdic["data"], err)
                                }
                                else {
                                    let errMsg = tdic["msg"]
                                    if let msg = errMsg {
                                        if msg is String {
                                           
                                            err = BLError.error(msg: msg as! String)     
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch{
            
                print("json解析失败")
                err = BLError.error(msg: "数据解析失败")
            }
        }
        
        if err == nil {
            err = BLError.error(msg: "数据解析失败")
        }
        return (nil, err)
    }
    
    // MARK: - 参数判断
    func check(_ para: Any?) -> Any {
        return para ?? "-8081"
    }
    
    func checkPara(_ paras: [Any]) -> Bool {
        for p in paras {
            if (p as? String) == "-8081" {
                return false
            }
        }
        return true
    }
    
    func paraError() -> NSError {
        return BLError.error(msg: "参数不正确")
    }
    
}


extension NSObject{
    
    /*
     示例：
     d = self.datasWithArr(arr:arr, modelName:"KJSpecialCategoryModel",dicToModelSelector:"modelWithDic:")
     */
    func datasWithArr(arr: Any?, modelName: String, dicToModelSelector: String) -> [Any]? {
        
        func swiftClassFromString(className: String) -> AnyClass! {
            // get the project name
            if  let appName: String = Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as! String? {
                // YourProject.className
                let classStringName = appName + "." + className
                return NSClassFromString(classStringName)
            }
            return nil;
        }
        
        guard arr != nil else {
            return nil
        }
        
        if arr! is [Dictionary<String, Any>] == false {
            return nil
        }
        
        let arr = arr as! [Dictionary<String, Any>]
        if arr.isEmpty==false {
            
            let sel = NSSelectorFromString(dicToModelSelector)
            let cls: AnyClass? = swiftClassFromString(className: modelName)//NSClassFromString(modelName)
            
            if let cls = cls {
                let c = cls as! NSObject.Type
                if c.responds(to: sel) {
                    var datas = [Any]()
                    
                    for dic in arr {
                        let m = c.perform(sel,with: dic)?.takeUnretainedValue()
                        if let model = m {
                            datas.append(model)
                        }
                    }
                    
                    if datas.isEmpty == false {
                        return datas
                    }
                }
            }
        }
        
        return nil
    }
    
    func datasWithDic(dic: Any?, dataKey: String, modelName: String, dicToModelSelector: String) -> Any? {
        
        if dic == nil {
            return nil
        }
        
        let cdic = dic!
        
        var tdic : Dictionary<String, Any>
        if cdic is Dictionary<String, Any> {
            tdic = (cdic as! Dictionary<String, Any>)
        }
        else{
            return nil
        }
        
        let arr = tdic[dataKey]
        guard arr != nil else {
            return nil
        }
        return self.datasWithArr(arr: arr!, modelName: modelName, dicToModelSelector: dicToModelSelector)
    }
}

